home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 14 / Example 14.1 / MasterAI.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-06-30  |  5.1 KB  |  231 lines

  1. #include "masterAI.h"
  2. #include "strategyMap.h"
  3.  
  4. //////////////////////////////////////////////////////////////////////////////////////////////
  5. //                                MASTERAI                                                    //
  6. //////////////////////////////////////////////////////////////////////////////////////////////
  7.  
  8. MASTERAI::MASTERAI(PLAYER *_player, TERRAIN *_terrain) : m_unitPool(this)
  9. {
  10.     m_pPlayer = _player;
  11.     m_pTerrain = _terrain;
  12.     m_nextGroupUpdate = 1.0f;
  13.     m_nextUpdate = 5.0f + m_pPlayer->m_teamNo;
  14.  
  15.     INTPOINT center = m_pPlayer->GetCenter();
  16.     RECT r = {center.x - 10, center.y - 10, center.x + 10, center.y + 10};
  17.     m_base = r;
  18.  
  19.     //Create influence map
  20.     m_pStrategyMap = new STRATEGY_MAP(m_pTerrain, m_pPlayer, INTPOINT(10, 10));
  21. }
  22.  
  23. MASTERAI::~MASTERAI()
  24. {
  25.     //Delete all groups
  26.     for(int i=0;i<m_groups.size();i++)
  27.         if(m_groups[i] != NULL)
  28.             delete m_groups[i];
  29.     m_groups.clear();
  30.  
  31.     //Release strategy map
  32.     if(m_pStrategyMap != NULL)
  33.         delete m_pStrategyMap;
  34. }
  35.  
  36. void MASTERAI::Update(float deltaTime)
  37. {
  38.     if(m_pPlayer == NULL || m_pTerrain == NULL)return;
  39.  
  40.     //Group AI update
  41.     m_nextGroupUpdate -= deltaTime;
  42.     if(m_nextGroupUpdate < 0.0f)
  43.     {
  44.         m_nextGroupUpdate = 3.0f;
  45.         HandleGroups();
  46.     }
  47.  
  48.     //Master AI Update
  49.     m_nextUpdate -= deltaTime;
  50.     if(m_nextUpdate < 0.0f)
  51.     {
  52.         m_nextUpdate = 10.0f;        
  53.         MasterAI();
  54.     }
  55. }
  56.  
  57. void MASTERAI::HandleGroups()
  58. {
  59.     //Add unassigned units/buildings to the unit pool
  60.     for(int m=0;m<m_pPlayer->m_mapObjects.size();m++)
  61.         if(m_pPlayer->m_mapObjects[m] != NULL && !m_pPlayer->m_mapObjects[m]->m_dead)
  62.             if(m_pPlayer->m_mapObjects[m]->m_pGroup == NULL)
  63.                 m_unitPool.AddMember(m_pPlayer->m_mapObjects[m]);
  64.  
  65.     //Update unit Pool
  66.     m_base = m_pPlayer->GetBaseArea();
  67.     m_unitPool.SetTask(TASK_DEFEND_LOCATION, &m_base);
  68.     m_unitPool.GroupAI();
  69.  
  70.     //Update other groups
  71.     std::vector<GROUPAI*>::iterator i;
  72.     for(i = m_groups.begin(); i != m_groups.end();)
  73.     {
  74.         if((*i) == NULL || (*i)->isDead())
  75.         {
  76.             delete (*i);
  77.             m_groups.erase(i);
  78.         }
  79.         else 
  80.         {
  81.             (*i)->GroupAI();
  82.             i++;
  83.         }
  84.     }
  85. }
  86.  
  87. void MASTERAI::MasterAI()
  88. {
  89.     //Update Influence map
  90.     if(m_pStrategyMap != NULL)
  91.         m_pStrategyMap->Update(m_visibleEnemies);
  92.  
  93.     m_visibleEnemies.clear();
  94.  
  95.     //Build buildings and train units
  96.     BuildManager();
  97.  
  98.     //Command units
  99.     StrategicManager();
  100. }
  101.  
  102. void MASTERAI::BuildManager()
  103. {
  104.     //Count number of buildings and units
  105.     int totNumUnits = 0;
  106.     int numUnits[3] = {0, 0, 0};
  107.     int numBuildings[3] = {0, 0, 0};
  108.  
  109.     for(int i=0;i<m_pPlayer->m_mapObjects.size();i++)
  110.         if(m_pPlayer->m_mapObjects[i] != NULL)
  111.         {
  112.             if(m_pPlayer->m_mapObjects[i]->m_isBuilding)
  113.                 numBuildings[m_pPlayer->m_mapObjects[i]->m_type]++;
  114.             else 
  115.             {
  116.                 numUnits[m_pPlayer->m_mapObjects[i]->m_type]++;
  117.                 totNumUnits++;
  118.             }
  119.         }
  120.  
  121.     //Cant train more units than the unit limit
  122.     if(totNumUnits >= m_pPlayer->unitLimit)
  123.         return;
  124.  
  125.     //Unit Ratio to maintain
  126.     float unitRatio[] = {0.1f, 0.5f, 0.4f};
  127.  
  128.     float greatestDifference = -1.0f;
  129.     int nextUnitToBuild = -1;
  130.  
  131.     //Calculate unit difference
  132.     for(int i=0;i<3;i++)
  133.     {
  134.         int aim = unitRatio[i] * totNumUnits;
  135.         float diff = (aim - numUnits[i]) / (float)totNumUnits;
  136.  
  137.         if(diff > greatestDifference)
  138.         {
  139.             greatestDifference = diff;
  140.             nextUnitToBuild = i;
  141.         }
  142.     }
  143.  
  144.     //Get Proper action
  145.     AI_ACTION *action = new TRAIN_UNIT(nextUnitToBuild);
  146.     AI_ACTION *preAction = NULL;
  147.  
  148.     do
  149.     {
  150.         preAction = action->RequiresAction(m_pPlayer);        
  151.         if(preAction != NULL)
  152.         {
  153.             delete action;
  154.             action = preAction;
  155.         }
  156.     }
  157.     while(preAction != NULL);
  158.  
  159.     //Perform action
  160.     if(action != NULL)
  161.     {
  162.         action->PerformAction(m_pPlayer);
  163.         delete action;
  164.     }
  165. }
  166.  
  167. void MASTERAI::StrategicManager()
  168. {
  169.     int numScoutGroups = 0;
  170.     int numAttackGroups = 0;
  171.  
  172.     for(int i=0;i<m_groups.size();i++)
  173.     {
  174.         if(m_groups[i]->m_task == TASK_SCOUT)
  175.             numScoutGroups++;
  176.         else if(m_groups[i]->m_task == TASK_ATTACK_LOCATION)
  177.             numAttackGroups++;
  178.     }
  179.  
  180.     //Create Scout Group
  181.     if(m_unitPool.m_members.size() > 4 && numScoutGroups < 2)
  182.     {
  183.         AREA* area = m_pStrategyMap->GetScoutArea(m_pPlayer->m_teamStartLocation);
  184.  
  185.         if(area != NULL)
  186.         {
  187.             std::vector<int> unit;
  188.             unit.push_back(WARRIOR);
  189.             GROUPAI *newGroup = m_unitPool.SplitGroup(unit);
  190.  
  191.             if(newGroup != NULL)
  192.             {                
  193.                 newGroup->SetTask(TASK_SCOUT, &area->m_mapArea);
  194.                 m_groups.push_back(newGroup);
  195.             }
  196.         }
  197.     }
  198.  
  199.     //Small attack
  200.     if(m_unitPool.m_members.size() > 8 && numAttackGroups == 0)
  201.     {
  202.         AREA *attackArea = m_pStrategyMap->GetAttackArea(m_pPlayer->m_teamStartLocation);
  203.         int numWarriors = 3 + rand()%4;
  204.  
  205.         std::vector<int> units;
  206.         for(int i=0;i<numWarriors;i++)
  207.             units.push_back(WARRIOR);
  208.  
  209.         //Create attack group
  210.         GROUPAI *newGroup = m_unitPool.SplitGroup(units);
  211.  
  212.         if(attackArea->Connected(m_pTerrain, newGroup->GetCenter()))
  213.         {
  214.             newGroup->SetTask(TASK_ATTACK_LOCATION, &attackArea->m_mapArea);
  215.             m_groups.push_back(newGroup);
  216.         }
  217.         else
  218.         {
  219.             newGroup->DisbandGroup();
  220.             delete newGroup;
  221.         }
  222.     }
  223. }
  224.  
  225. void MASTERAI::EnemiesSpotted(std::vector<MAPOBJECT*> &manyEnemies)
  226. {
  227.     if(m_visibleEnemies.size() >= 30)return;
  228.  
  229.     for(int i=0;i<manyEnemies.size();i++)
  230.         m_visibleEnemies.insert(manyEnemies[i]);
  231. }